#ifndef DRAWING_H
#define DRAWING_H

/* Colors */

#define RGB(r,g,b) (unsigned short)((r)+((g) << 5 ) + ((b) << 10 ))

#define COLOR_WHITE RGB(31,31,31)
#define COLOR_BLACK RGB(0,0,0)
#define COLOR_RED RGB(31,0,0)
#define COLOR_YELLOW RGB(31,31,0)
#define COLOR_BLUE RGB(0,0,31)
#define COLOR_GREEN RGB(0,31,0)

typedef unsigned short Color;

/* End of Colors */

/* Font Nonsense */

unsigned short * font;

#define SetFont(f) (font=f)

#define FONT_WIDTH 8
#define FONT_HEIGHT 8

/* End of Font Nonsense */

/* Mode 5 Drawing Functions */

void DrawPixel5(int x, int y, unsigned short c)
{
    videoBuffer[ y * 160 + x ] = c;
}

void DrawChar5(int left, int top, char letter, unsigned short color)
{
  int x, y;
  int draw;
  for(y = 0; y < 8; y++)
    for (x = 0; x < 8; x++)
    {
      // grab a pixel from the font char
      draw = font[(letter-32) * 64 + y * 8 + x];

      // if pixel = 1, then draw it
      if (draw)
        DrawPixel5(left + x, top + y, color);//or other DrawPixel function
    }
}

void Print5(int left, int top, char *str, unsigned short color)
{
    int pos = 0;
    while (*str)
    {
        DrawChar5(left + pos, top, *str++, color);
        pos += 8;
    }
}

/* End of Mode 5 Drawing Functions */

/* Mode 4 Drawing Functions */

void DrawPixel4(int x, int y, unsigned char color)
{
    unsigned short pixel;
    unsigned short offset = (y * 240 + x) >> 1;
    pixel = videoBuffer[offset];
    if (x & 1)
        videoBuffer[offset] = (color << 8) + (pixel & 0x00FF);
    else
        videoBuffer[offset] = (pixel & 0xFF00) + color;
}

void DrawChar4(int left, int top, char letter, unsigned short color)
{
  int x, y;
  int draw;
  for(y = 0; y < 8; y++)
    for (x = 0; x < 8; x++)
    {
      // grab a pixel from the font char
      draw = font[(letter-32) * 64 + y * 8 + x];

      // if pixel = 1, then draw it
      if (draw)
        DrawPixel4(left + x, top + y, color);//or other DrawPixel function
    }
}

void Print4(int left, int top, char *str, unsigned short color)
{
    int pos = 0;
    while (*str)
    {
        DrawChar4(left + pos, top, *str++, color);
        pos += 8;
    }
}

void DrawBox4(int left, int top, int right, int bottom, unsigned short color)
{
    int x, y;
    for(y = top; y < bottom; y++)
        for(x = left; x < right; x++)
            DrawPixel4(x, y, color);
}

void DrawImage4( unsigned char const * p_image, int x, int y, int image_width, int image_height )
{
    int i;

    for ( i = 0 ; i < image_width * image_height ; ++i )
    {
        DrawPixel4(
            x + ( i % image_width ),
            y + ( i / image_width ),
            p_image[ i ] );
    }
}

/* End of Mode 3 Drawing Functions */

/* Mode 3 Drawing Functions */

inline void DrawPixel3( int const x, int const y, Color const color )
{
	if ( ( x >= 0 && x < SCREEN_WIDTH ) && ( y >= 0 && y < SCREEN_HEIGHT ) )
		videoBuffer[ y * SCREEN_WIDTH + x ] = color;
}


void DrawChar3(int left, int top, char letter, unsigned short color)
{
  int x, y;
  int draw;
  for(y = 0; y < 8; y++)
    for (x = 0; x < 8; x++)
    {
      // grab a pixel from the font char
      draw = font[(letter-32) * 64 + y * 8 + x];

      // if pixel = 1, then draw it
      if (draw)
        DrawPixel3(left + x, top + y, color);//or other DrawPixel function
    }
}

void Print3(int left, int top, char *str, unsigned short color)
{
    int pos = 0;
    while (*str)
    {
        DrawChar3(left + pos, top, *str++, color);
        pos += 8;
    }
}

void DrawLine3(int x1, int y1, int x2, int y2, unsigned short color)
{
	int i, deltax, deltay, numpixels;
	int d, dinc1, dinc2;
	int x, xinc1, xinc2;
	int y, yinc1, yinc2;
	//calculate deltaX and deltaY
	deltax = abs(x2 - x1);
	deltay = abs(y2 - y1);
	//initialize
	if(deltax >= deltay)
	{
		//If x is independent variable
		numpixels = deltax + 1;
		d = (2 * deltay) - deltax;
		dinc1 = deltay << 1;
		dinc2 = (deltay - deltax) << 1;
		xinc1 = 1;
		xinc2 = 1;
		yinc1 = 0;
		yinc2 = 1;
	}
	else
	{
		//if y is independant variable
		numpixels = deltay + 1;
		d = (2 * deltax) - deltay;
		dinc1 = deltax << 1;
		dinc2 = (deltax - deltay) << 1;
		xinc1 = 0;
		xinc2 = 1;
		yinc1 = 1;
		yinc2 = 1;
	}

    //move the right direction
	if(x1 > x2)
	{
		xinc1 = -xinc1;
		xinc2 = -xinc2;
	}
	if(y1 > y2)
	{
		yinc1 = -yinc1;
		yinc2 = -yinc2;
	}
	x = x1;
	y = y1;
	//draw the pixels
	for(i = 1; i < numpixels; i++)
	{
		DrawPixel3(x, y, color);
		if(d < 0)
		{
		    d = d + dinc1;
		    x = x + xinc1;
		    y = y + yinc1;
		}
		else
		{
		    d = d + dinc2;
		    x = x + xinc2;
		    y = y + yinc2;
		}
	}
}


void DrawCircle3(int xCenter, int yCenter, int radius, unsigned short color)
{
	int x = 0;
	int y = radius;
	int p = 3 - 2 * radius;
	while (x <= y)
	{
		DrawPixel3(xCenter + x, yCenter + y, color);
		DrawPixel3(xCenter - x, yCenter + y, color);
		DrawPixel3(xCenter + x, yCenter - y, color);
		DrawPixel3(xCenter - x, yCenter - y, color);
		DrawPixel3(xCenter + y, yCenter + x, color);
		DrawPixel3(xCenter - y, yCenter + x, color);
		DrawPixel3(xCenter + y, yCenter - x, color);
		DrawPixel3(xCenter - y, yCenter - x, color);
		if (p < 0)
			p += 4 * x++ + 6;
		else
			p += 4 * (x++ - y--) + 10;
	}
}


void DrawBox3(int left, int top, int right, int bottom, unsigned short color)
{
    int x, y;
    for(y = top; y < bottom; y++)
        for(x = left; x < right; x++)
            DrawPixel3(x, y, color);
}


void DrawImage3( unsigned short const * p_image, int x, int y, int image_width, int image_height )
{
    int i;

    for ( i = 0 ; i < image_width * image_height ; ++i )
    {
        DrawPixel3(
            x + ( i % image_width ),
            y + ( i / image_width ),
            p_image[ i ] );
    }
}

/* End of Mode 3 Drawing Functions */

void screenFill3( unsigned short color )
{
    int X = 0; //screenWidth / 2;
    int Y = 0;// screenHeight / 2;


    for ( Y = 0 ; Y < SCREEN_HEIGHT ; ++Y )
    {
        for ( X = 0 ; X < SCREEN_WIDTH ; ++X )
        {
            DrawPixel3(
                X,
                Y,
                color
                );
        }
    }
}

void screenFill4( unsigned short color )
{
    int X = 0; //screenWidth / 2;
    int Y = 0;// screenHeight / 2;


    for ( Y = 0 ; Y < SCREEN_HEIGHT ; ++Y )
    {
        for ( X = 0 ; X < SCREEN_WIDTH ; ++X )
        {
            DrawPixel4(
                X,
                Y,
                color
                );
        }
    }
}

#endif
